/*************************************************
 * 
 * Copyright by Bruno Eberhard
 * 
 * Created on 29.07.2005
 *
 *************************************************/
package fightplan.views.tables;

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.RowFilter;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter;

import com.jgoodies.binding.value.ValueModel;
import com.jgoodies.forms.builder.DefaultFormBuilder;
import com.jgoodies.forms.layout.FormLayout;

import fightplan.actions.UndoRedoManager;
import fightplan.actions.UndoRedoManagerProvider;
import fightplan.actions.UndoableAction;
import fightplan.business.AbstractFighter;
import fightplan.business.Category;
import fightplan.business.Dojo;
import fightplan.business.Fighter;
import fightplan.business.Gender;
import fightplan.business.Tournament;
import fightplan.business.Validation;
import fightplan.core.NotEmptyValidation;
import fightplan.core.NotZeroValidation;
import fightplan.core.Style;
import fightplan.ui.BeanListTableModel;
import fightplan.ui.BeanPropertyTableCellRenderer;
import fightplan.views.MainView;

@SuppressWarnings("serial")
public class FighterTable extends JPanel implements PropertyChangeListener, UndoRedoManagerProvider {
	private JTable table;
	private BeanListTableModel<Fighter> tableModel;
	private TableColumn columnName, columnGender, columnYear, columnWeight, columnBelt, columnDojo, columnCategory;
	private TableRowSorter<BeanListTableModel<?>> sorter;
	private ValueModel tournamentModel;
	
	public FighterTable(ValueModel tournamentModel) {
		super(new BorderLayout());
		this.tournamentModel = tournamentModel;
		tournamentModel.addValueChangeListener(this);

		table = new JTable(tableModel);
		table.setRowHeight(20);
		
		createTableModel();
		updateTableModel();
		
		table.putClientProperty(fightplan.actions.SelectAllAction.MENU_CONTROLLED, Boolean.TRUE);
		table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
		sorter = new TableRowSorter<BeanListTableModel<?>>(tableModel);
		table.setRowSorter(sorter);

		JScrollPane scrollPane = new JScrollPane(table);
		scrollPane.setPreferredSize(new Dimension(5000, 5000));
		scrollPane.getViewport().setBackground(Style.UNUSED_TABLE_SPACE);
		add(createFilter(), BorderLayout.NORTH);
		add(scrollPane, BorderLayout.CENTER);
		add(fighterAction(), BorderLayout.SOUTH);
	}

	private Tournament getTournament() {
		return (Tournament) tournamentModel.getValue();
	}

	private JPanel fighterAction() {
		JPanel panel = new JPanel(new BorderLayout());
		panel.add(createAddRemoveAction(), BorderLayout.EAST);
		return panel;
	}

	public UndoRedoManager getUndoRedoManager() {
		return ((MainView) SwingUtilities.getWindowAncestor(this)).getUndoRedoManager();
	}

	private JPanel createAddRemoveAction() {
		JPanel panel = new JPanel(new FlowLayout(SwingConstants.RIGHT));
		panel.add(createDeleteButton());
		panel.add(createNewButton());
		return panel;
	}

	private JButton createNewButton() {
		final Action deleteAction = new UndoableAction("Teilnehmer hinzufügen", this, "Teilnehmer wieder entfernen") {
			public boolean doAction(ActionEvent e) {
				tableModel.addElement(new Fighter());
				return true;
			}
		};
		return new JButton(deleteAction);
	}

	private JButton createDeleteButton() {
		final Action deleteAction = new UndoableAction("Teilnehmer löschen", this, "Teilnehmer wieder herstellen") {
			public boolean doAction(ActionEvent e) {
				boolean confirm = JOptionPane.showConfirmDialog(FighterTable.this,
						"Wollen Sie diese(n) Teilnehmer wirklich löschen?", "Teilnehmer löschen",
						JOptionPane.YES_NO_OPTION) == JOptionPane.OK_OPTION;
				if (!confirm)
					return false;
				for (int i = table.getRowCount() - 1; i >= 0; i--) {
					if (!table.isRowSelected(i))
						continue;
					Fighter fighter = tableModel.getList().get(i);
					for (Category category : fighter.searchCategories(getTournament())) {
						category.getFighters().remove(fighter);
					}
					tableModel.removeElement(fighter);
				}
				return true;
			}
		};
		deleteAction.setEnabled(table.getSelectedRows().length >= 1);
		table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
			public void valueChanged(ListSelectionEvent e) {
				deleteAction.setEnabled(table.getSelectedRows().length >= 1);
			}
		});
		return new JButton(deleteAction);
	}

	private JPanel createFilter() {
		FormLayout layout = new FormLayout("left:pref, 4dlu, pref:grow(1), 20dlu", "20dlu"); // add
																								// rows
																								// dynamically

		final JTextField textField = new JTextField();
		textField.getDocument().addDocumentListener(new DocumentListener() {

			public void changedUpdate(DocumentEvent e) {
				updateFilter();
			}

			public void insertUpdate(DocumentEvent e) {
				updateFilter();
			}

			public void removeUpdate(DocumentEvent e) {
				updateFilter();
			}

			private void updateFilter() {
				String text = textField.getText();
				if (text == null || text.trim().length() == 0) {
					sorter.setRowFilter(null);
				} else {
					sorter.setRowFilter(RowFilter.regexFilter(".*" + text + ".*"));
				}
			}
		});

		DefaultFormBuilder builder = new DefaultFormBuilder(layout);
		builder.append("Suche", textField);
		return builder.getPanel();
	}

	//

	public void propertyChange(PropertyChangeEvent evt) {
		updateTableModel();
		Tournament t = (Tournament) tournamentModel.getValue();
		tableModel.setList(t.getFighters());
	}

	private void createTableModel() {
		tableModel = new BeanListTableModel<Fighter>(null, new String[] { "name", "gender", "yearFormatted",
				"weightFormatted", "beltFormatted", "dojo", null }, new String[] { "Name", "D/H", "Jahrgang",
				"Gewicht", "Gurt", "Dojo", "Kategorien" }, new Class[] { String.class, Object.class, Object.class,
				Object.class, Object.class, Dojo.class, Object.class });
		table.setModel(tableModel);
		
		JTextField textField = new JTextField();
		textField.setBorder(null);
		TableCellEditor editor = new InfoCellEditor(new DefaultCellEditor(textField));
		TableColumnModel cm = table.getColumnModel();
		
		columnName = cm.getColumn(0);
		columnName.setCellRenderer(new BeanPropertyTableCellRenderer(new NotEmptyValidation()));
		columnName.setCellEditor(new LimitedCellEditor(25));
		columnName.setPreferredWidth(160);

		columnGender = cm.getColumn(1);
		columnGender.setPreferredWidth(50);
		columnGender.setMaxWidth(50);
		columnGender.setCellRenderer(new BeanPropertyTableCellRenderer("nameLong"));
		columnGender.setCellEditor(new GenderCellEditor(Gender.VALUES));
		
		columnYear = cm.getColumn(2);
		columnYear.setCellRenderer(new BeanPropertyTableCellRenderer(new NotZeroValidation()));
		columnYear.setPreferredWidth(55);
		columnYear.setMaxWidth(75);
		columnYear.setCellEditor(editor);
		
		columnWeight = cm.getColumn(3);
		columnWeight
				.setCellRenderer(
						new BeanPropertyTableCellRenderer(new NotEmptyValidation(Validation.YELLOW,
								"Gewicht möglich angeben.")));
		columnWeight.setPreferredWidth(55);
		columnWeight.setMaxWidth(75);
		
		columnBelt = cm.getColumn(4);
		columnBelt.setPreferredWidth(45);
		columnBelt.setMaxWidth(55);
		
		columnDojo = cm.getColumn(5);
		columnDojo.setCellEditor(new DojoCellEditor(tournamentModel, table, false));
		columnDojo.setCellRenderer(
				new BeanPropertyTableCellRenderer("name", new NotEmptyValidation(Validation.YELLOW,
						"Dojo wenn möglich angeben.")));
		columnDojo.setPreferredWidth(90);
		
		columnCategory = cm.getColumn(6);
		columnCategory.setCellEditor(new CategoryCellEditor(tournamentModel));
		columnCategory.setCellRenderer(new CategoriesTableCellRenderer(tournamentModel));
		columnCategory.setPreferredWidth(300);
	}
	
	private void updateTableModel() {
		TableColumnModel columnModel = table.getColumnModel();

		// dont remove name, gender, year
		for (int i = columnModel.getColumnCount()-1; i > 2; i--) {
			columnModel.removeColumn(columnModel.getColumn(i));
		}
		
		boolean showWeight = getTournament() == null || getTournament().getMode().hasWeights();
		boolean showBelt = getTournament() == null || getTournament().getMode().hasBelts();
		
		if (showWeight) {
			columnModel.addColumn(columnWeight);
		}
		
		if (showBelt) {
			columnModel.addColumn(columnBelt);
		}

		columnModel.addColumn(columnDojo);
		columnModel.addColumn(columnCategory);
	}

	//

	static class CategoriesTableCellRenderer extends DefaultTableCellRenderer {
		private ValueModel tournament;

		public CategoriesTableCellRenderer(ValueModel tournament) {
			this.tournament = tournament;
		}

		@Override
		public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,
				boolean hasFocus, int row, int column) {
			value = ((AbstractFighter) value).getCategoryNames((Tournament) tournament.getValue());
			setOpaque(true);
			return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
		}

	}

}
